/**
 * @file       Thread.cpp
 * @brief      TODO
 * @author     Huabo Zheng
 * @date       Jan 19, 2012
 * @Copyright  2012, www.netgear.com Inc. All rights reserved.
 */

#include "Thread.h"
#include "typedefine.h"
#include "errorcode.h"

namespace NS_LCD_AFW
{

CThread::CThread() :
		m_bAutoDelete(true), m_state(eReady)
{
}

CThread::CThread(bool bAutoDelete) :
		m_bAutoDelete(bAutoDelete), m_state(eReady)
{

}

CThread::~CThread()
{
	m_state = eStop;
}

bool CThread::isAutoDelete()
{
	return this->m_bAutoDelete;
}

void CThread::setAutoDelete(bool bAutoDelete)
{
	m_bAutoDelete = bAutoDelete;
}

void CThread::onException()
{
}

void CThread::onExit()
{
}

int CThread::start()
{
	if (this->isRunning())
	{
		return ERR_THREAD_IS_RUNNING;
	}

	/*
	 * When a joinable thread terminates, its memory
	 * resources (thread descriptor and stack) are not
	 * deallocated until another thread performs
	 * pthread_join on it. Therefore,
	 * pthread_join must be called once for
	 *  each joinable thread created to avoid memory leaks.
	 * */
//	pthread_attr_t attr;
//	pthread_attr_init(&attr);
//	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

	int iErrCode = pthread_create(&m_tId, NULL, threadFunc, this);

	if (iErrCode != 0)
	{
		//pthread_attr_destroy(&attr);
		return iErrCode;
	}

	//pthread_attr_destroy(&attr);

	while (!isRunning())
	{
	};
	return ERR_SUCCESS;
}

int CThread::join()
{
	if (eReady == this->m_state)
	{
		return ERR_THREAD_NOT_RUNNING;
	}
	return pthread_join(m_tId, NULL);
}

//int CThread::stop()
//{
//	return ERR_SUCCESS;
//}

bool CThread::isRunning()
{
	return (eRunning == m_state);
}

void *CThread::threadFunc(void *pArg)
{
	CThread *pThread = static_cast<CThread *>(pArg);

	pThread->m_state = eRunning;
	try
	{
		pThread->run();
	} catch (...)
	{
		pThread->onException();
	}

	pThread->m_state = eStop;

	if (pThread->isAutoDelete())
	{
		pthread_detach(pthread_self());
		OBJ_DELETE(pThread);
	}


	pThread = NULL;
	return 0;
}

} /* namespace NS_LCD_AFW */
